package hasthi.tools;

import hasthi.manager.ManagerPingRequestDocument;
import hasthi.manager.ManagerPingResponseDocument;
import hasthi.manager.ManagementRingDocument.ManagementRing;
import hasthi.manager.ManagementRingDocument.ManagementRing.ManagerData;
import hasthi.manager.gui.UIContext;
import hasthi.metamodel.ResourceModelFactory;
import hasthi.tools.analyze.DataSetBag;
import hasthi.tools.analyze.PerfClient;
import hasthi.tools.analyze.PerfClient.PerfResponseVerifier;

import java.util.concurrent.Semaphore;

import org.apache.xmlbeans.XmlObject;

public class ManagementRingMeter{
    private Semaphore rendezvous = new Semaphore(0,true);
    private int managerCount = 1;
    
    
    public void startTest() throws Exception{
        UIContext uicontext = new UIContext(true);
        ManagementRing managementRing = null;
        
        
        while(managementRing == null || managementRing.getManagerDataArray().length < managerCount){
            Thread.sleep(1000);
            managementRing = ResourceModelFactory.getManagerRingState(uicontext);
        }
        
        ManagerData[] managerData= managementRing.getManagerDataArray();
        
        String name = "ringTest"+managementRing.getManagerDataArray().length;
        
        
        ManagerPingRequestDocument pingRequestDocument = ManagerPingRequestDocument.Factory.newInstance();
        pingRequestDocument.addNewManagerPingRequest();
        
        PerfResponseVerifier coordinatorVerifier =new PerfResponseVerifier() {
            public boolean verify(XmlObject response) {
                if(response instanceof ManagerPingResponseDocument){
                    return ((ManagerPingResponseDocument)response)
                        .getManagerPingResponse().getManagerContext().getManagementRing() != null;
                }
               return false;
            }
        };
        
        PerfResponseVerifier managerVerifier =new PerfResponseVerifier() {
            public boolean verify(XmlObject response) {
                return response instanceof ManagerPingResponseDocument;
            }
        };
        
        PerfClient[] perfClients = new PerfClient[managerCount+1];
        
        
        for (int i = 0; i < managerCount+1 ; i++) {
            if(i == 0){
                System.out.println("Coordinator = "+uicontext.getCoordinatorUrl());
                perfClients[i] = new PerfClient(name+"[" +i + "]",uicontext.getCoordinatorUrl(),
                        1000,100, coordinatorVerifier,pingRequestDocument);
            }else{
                System.out.println("Manager = "+managerData[i-1].getManagerAddress().getSoapAddress() + " "+ managerData[i-1].getResourceDataArray().length);
                perfClients[i] = new PerfClient(name+"[" +i + "]",managerData[i-1].getManagerAddress().getSoapAddress(),
                        1000,100, managerVerifier,pingRequestDocument);
            }
            RunnableWrapper wrapper = new RunnableWrapper(perfClients[i]);
            Thread t = new Thread(wrapper);
            t.setDaemon(true);
            t.start();
        }
        
        rendezvous.acquire(managerCount+1);
        DataSetBag coordonatorDataSet = new DataSetBag(name);
        coordonatorDataSet.addData(perfClients[0].getDataCollector());
        System.out.println("====COORDINATOR RESULTS=====");
        coordonatorDataSet.sendSummery();
        
        DataSetBag dataSet = new DataSetBag(name);
        
        for (int i = 0; i < managerCount ; i++) {
            dataSet.addData(perfClients[i+1].getDataCollector());
        }
        System.out.println("====MANAGER RESULTS=====");
        dataSet.sendSummery();
        
    }
    
    public class RunnableWrapper implements Runnable{
        private Runnable runnable;
        private RunnableWrapper(Runnable runnable){
            this.runnable = runnable;
        }
     public void run() {
         try {
             runnable.run();
         }finally {
             rendezvous.release();
         }
     }
    }
    
    public static void main(String[] args) throws Exception {
        ManagementRingMeter managementRingMeter = new ManagementRingMeter();
        managementRingMeter.startTest();
    }
    
}
